uniform sampler2D positionMap;
uniform sampler2D normalMap;
uniform int numSurfaces;
attribute float my_Surface;

varying vec3 N;
varying vec3 v;

varying float totalOcclusion;

float occlusion(float d2, float cosOr, float cosOe, float emitterArea){
	return 1.0 - inversesqrt(emitterArea/d2 + 1.0) * clamp(cosOe, 0.0, 1.0) * clamp(4.0 * cosOr, 0.0, 1.0);
}

float ambientOcclusion(){
	
	float flag = 0.0;
	float value;
	float total = 0.0;
	float d, d2, cosOe, cosOr;
	float emitterArea;
	vec3 emitterPos;
	vec4 emitterNormal;
	vec3 v;
	vec2 eTexCoord, rTexCoord;
	
	rTexCoord.x = int(my_Surface)/256;
	rTexCoord.y = int(my_Surface)%256;
	vec3 receiverPos = texture2D(positionMap, rTexCoord.xy).xyz;
	vec3 receiverNormal = texture2D(normalMap, rTexCoord.xy).xyz;
	
	for(int e = 0; e < numSurfaces; e++){
		
		eTexCoord.x = float(e/256);
		eTexCoord.y = float(e%256);
		
		if(!(rTexCoord.x == eTexCoord.x && rTexCoord.y == rTexCoord.y)){
			emitterPos = texture2D(positionMap, eTexCoord.xy).xyz;
			emitterNormal = texture2D(normalMap, eTexCoord.xy);
			emitterArea = emitterNormal.w;
			
			v = emitterPos - receiverPos;
			d = length(v);
			d2 = dot(v, v);
			normalize(v);
			
			//if (d2 < -emitterArea) { // (parents have negative area)
			//	emitterArea = 0.0; // ignore this element
			//}
			
			cosOr = dot(receiverNormal, v);
			cosOe = dot(emitterNormal.xyz, v);
			value = occlusion(d2, cosOr, cosOe, abs(emitterArea));
			
			receiverNormal -= value * v;
			
			total += value;
		}

	}
	//normalize(receiverNormal);
	
	return my_Surface/670.0;
}

void main(void){

	v = vec3(gl_ModelViewMatrix * gl_Vertex);       
	N = normalize(gl_NormalMatrix * gl_Normal);

	totalOcclusion = ambientOcclusion();
	//totalOcclusion = my_Surface/670.0;;
	
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
